package com.cti.ftpservice.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.mchange.v2.lang.StringUtils;

public class ZipUtils {

	static final int BUFFER = 4096;

	private static Log log = LogFactory.getLog(ZipUtils.class);

	/**
	 * 压缩
	 * 
	 * @param sourceFilePath
	 *            原始文件或文件夹路径
	 * @param targetFilePath
	 *            目标文件或文件夹路径
	 * @return
	 * @throws Exception
	 */
	public static void Zip(String sourceFilePath, String targetFilePath) throws Exception {
		File sourceFile = new File(sourceFilePath);
		if (!sourceFile.exists())
			return;
		FileOutputStream dest = null;
		ZipOutputStream out = null;
		try {
			dest = new FileOutputStream(targetFilePath);
			out = new ZipOutputStream(new BufferedOutputStream(dest));
			zipFile(out, sourceFile, null);
		} finally {
			try {
				if (out != null) {
					out.close();
				}
				if (dest != null) {
					dest.close();
				}
			} catch (Exception e) {
			}
		}
	}

	private static void zipFile(ZipOutputStream out, File sourceFile, String base) throws Exception {

		log.info("开始压缩");
		if (sourceFile.isDirectory()) {
			File[] files = sourceFile.listFiles();
			if (base != null) {
				out.putNextEntry(new ZipEntry(base + "/"));
			}
			base = base == null ? "" : base + "/";
			for (int i = 0; i < files.length; i++) {
				zipFile(out, files[i], base + files[i].getName());
			}
		} else {
			if (base == null)
				base = sourceFile.getName();
			ZipEntry entry = new ZipEntry(base);
			out.putNextEntry(entry);
			FileInputStream origin = null;
			int buffer=BUFFER;
			if(sourceFile.length()>Integer.MAX_VALUE){
				log.info(base+"文件太大！");
				 return;
			}else if(sourceFile.length()>buffer) {
            	buffer=(int)sourceFile.length();
            }
			try {
				origin = new FileInputStream(sourceFile);
				byte data[] = new byte[buffer];
				int count;
				while ((count = origin.read(data, 0, buffer)) != -1) {
					out.write(data, 0, count);
				}

			} finally {
				try {
					if (origin != null) {
						origin.close();
					}
				} catch (Exception e) {
				}
			}
		}

		log.info("压缩完成");
	}

	/**
	 * 解压 解压到当前目录
	 * 
	 * @param zipFilePath
	 * @throws Exception
	 */
	public static List<String> unZip(String zipFilePath) throws Exception {
		return unZip(zipFilePath, null);
	}

	/**
	 * 解压 解压到制定文件夹下
	 * 
	 * @param zipFilePath
	 * @param targetFileParentDirPath
	 * @return List<String> 解压后所有文件的绝对路径
	 * @throws Exception
	 * 
	 */
	public static List<String> unZip(String zipFilePath, String targetFileParentDirPath) throws Exception {

		List<String> filePaths = new ArrayList<String>();
		ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));// 输入源zip路径
		
		
		BufferedInputStream bufferedInputStream = new BufferedInputStream(zipInputStream);
		String basePath = FilenameUtils.getFullPath(zipFilePath);
		if (StringUtils.nonEmptyString(targetFileParentDirPath)) {
			basePath = FilenameUtils.getFullPath(targetFileParentDirPath);
		}
		
		
		File outFile = null;
		ZipEntry entry;

		while ((entry = zipInputStream.getNextEntry()) != null && !entry.isDirectory()) {
			outFile = new File(basePath, entry.getName());
			if (!outFile.exists()) {
				(new File(outFile.getParent())).mkdirs();
			}
			filePaths.add(outFile.getAbsolutePath());
			FileOutputStream outputStream = new FileOutputStream(outFile);
			BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
			int count;
			int buffer=BUFFER;
			if(outFile.length()>Integer.MAX_VALUE){
				log.info(outFile.getName()+"文件太大！");
				continue;
			}else if(outFile.length()>buffer) {
            	buffer=(int)outFile.length();
            }
			byte[] bs = new byte[buffer];
			while ((count = bufferedInputStream.read(bs, 0, bs.length)) != -1) {
				bufferedOutputStream.write(bs, 0, count);
			}
			bufferedOutputStream.close();
			outputStream.close();
		}
		bufferedInputStream.close();
		zipInputStream.close();
		return filePaths;
	}
	
	@SuppressWarnings("rawtypes")
	public static List<ISOTemp> ParseXmlFile(File zipedFile) throws Exception {
		List<ISOTemp> temps = new ArrayList<ISOTemp>();
		SAXReader reader = new SAXReader();
		Document document = reader.read(zipedFile);
		Element rootElement = document.getRootElement();
		
		List bookElements = rootElement.elements("isofile");
		for (Iterator iterator = bookElements.iterator(); iterator.hasNext();) {
			Element bookElement = (Element) iterator.next();
			ISOTemp temp = new ISOTemp();

			// author
			String creatorId = bookElement.element("creatorId").getText();
			creatorId = StringUtils.nonEmptyTrimmedOrNull(creatorId);
			temp.creatorId = creatorId;

			// binding
			String data = bookElement.element("fileData").getText();
			data = StringUtils.nonEmptyTrimmedOrNull(data);
			temp.data = data;
			
			try {
				//encoding
				String encoding = bookElement.element("encoding").getText();
				encoding = StringUtils.nonEmptyTrimmedOrNull(encoding);
				temp.encoding = encoding;
			} catch (Exception e) {
			}
			
			
			

			if (!org.apache.commons.lang3.StringUtils.isBlank(creatorId) && !org.apache.commons.lang3.StringUtils.isBlank(data)) {
				temp.data = Base64CoderUtils.decoderString(temp.data);
				temps.add(temp);
			}
		}
		return temps;
	}

	public static class ISOTemp {
		public String creatorId;
		public String data;
		public String encoding;
	}
}
